﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Net;

namespace eCompany.eApi
{
    public class api
    {
        public delegate void updateCaller(string action);

        public double currency_getRate(string fromCurrency, string toCurrency)
        {
            XmlTextReader rd = new XmlTextReader("http://api.erepublik.com/v2/feeds/exchange/" + fromCurrency + "/" + toCurrency);
            System.Xml.XmlDocument doc = new XmlDocument();
            doc.Load(rd);
            XmlNodeList lst = doc.SelectNodes("offers/offer/exchange-rate");
            double min_value = double.MaxValue;
            foreach (XmlNode n in lst)
            {
                double current_value;
                current_value = Convert.ToDouble(n.InnerText.Replace(".", ","));
                if (current_value < min_value)
                    min_value = current_value;
            }
            return min_value;
        }

        public eObj.company loadCompanyFromWeb(string company_id, updateCaller caller)
        {
            try
            {
                System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo("en-US");

                if(caller != null) caller("Loading Countries. It may take 1min");
                HttpWebRequest hwebRequest = (HttpWebRequest)WebRequest.Create("http://api.erepublik.com/v2/feeds/countries"); 
                hwebRequest.Timeout = 60000;
                hwebRequest.ReadWriteTimeout = 60000;
                HttpWebResponse hWebResponse = (HttpWebResponse)hwebRequest.GetResponse(); 
                XmlTextReader oXmlReader = new XmlTextReader(hWebResponse.GetResponseStream()); 

                //XmlTextReader rd = new XmlTextReader("http://api.erepublik.com/v2/feeds/countries");
                System.Xml.XmlDocument countries_doc = new XmlDocument();
                //countries_doc.Load(rd);
                countries_doc.Load(oXmlReader);

                if (caller != null) caller("Loading Company. It may take 1min");
                hwebRequest = (HttpWebRequest)WebRequest.Create("http://api.erepublik.com/v2/feeds/companies/" + company_id);
                hwebRequest.Timeout = 60000;
                hwebRequest.ReadWriteTimeout = 60000; 
                hWebResponse = (HttpWebResponse)hwebRequest.GetResponse();
                oXmlReader = new XmlTextReader(hWebResponse.GetResponseStream()); 
                
                //rd = new XmlTextReader("http://api.erepublik.com/v2/feeds/companies/" + company_id);
                System.Xml.XmlDocument doc = new XmlDocument();
                doc.Load(oXmlReader);

                if (caller != null) caller("Processing Company");
                eObj.company comp = new eObj.company();
                comp.id = Guid.NewGuid().ToString();
                comp.api_id = company_id;

                //Company Name
                XmlNode nd = doc.SelectSingleNode("company/name");
                comp.name = nd.InnerText;

                //Company Type
                nd = doc.SelectSingleNode("company/industry/id");
                comp.type = getCompanyTypeFromApiId(nd.InnerText);
                string industry_id = nd.InnerText;

                //Custom Points
                comp.customized_point = 0;
                Dictionary<string, string> customPointsTab = new Dictionary<string, string>();
                nd = doc.SelectSingleNode("company/customization");
                foreach (XmlNode _nd in nd.ChildNodes)
                {
                    if (_nd.InnerText != "")
                        comp.customized_point += Int32.Parse(_nd.InnerText, culture);
                    customPointsTab.Add(_nd.Name, _nd.InnerText);
                }
                if (comp.customized_point == 0) comp.customized_point = 1;

                //Custom Level
                comp.customized_level = 0;
                nd = doc.SelectSingleNode("company/customization-level");
                comp.customized_level = int.Parse(nd.InnerText);
                
                //GLD Account
                eObj.account acc = new eObj.account();
                acc.id = Guid.NewGuid().ToString();
                acc.currency = "GLD";
                acc.name = "Account GLD";
                comp.account_list.Add(acc);

                //Shops and accounts
                nd = doc.SelectSingleNode("company/country/id");
                nd = countries_doc.SelectSingleNode("countries/country[id=" + nd.InnerText + "]/currency");
                string default_cur = nd.InnerText;
                XmlNodeList ndl = doc.SelectNodes("company/export-licenses/export-license/country/id");
                foreach (XmlNode n in ndl)
                {
                    string country_id = n.InnerText;
                    XmlNode n2 = countries_doc.SelectSingleNode("countries/country[id=" + country_id + "]/currency");
                    string country_cur = n2.InnerText;

                    eObj.account a = new eObj.account();
                    a.id = Guid.NewGuid().ToString();
                    a.name = "Account " + country_cur;
                    a.currency = country_cur;
                    if (country_cur == default_cur)
                        comp.default_account = a.id;
                    comp.account_list.Add(a);

                    eObj.shop s = new eObj.shop();
                    s.currency = country_cur;
                    /*double volume, unit_price;
                    getMarketForCompany(company_id, industry_id, country_id, customPointsTab, out volume, out unit_price);
                    if (volume > 0)
                    {
                        eObj.shop_stock ss = new eObj.shop_stock();
                        ss.date = DateTime.Today;
                        ss.unit_price = unit_price;
                        ss.volume_in = volume;
                        ss.volume_out = 0;
                        s.stocks.Add(ss);
                    }*/
                    comp.shops.Add(s);
                }

                //Materials
                if (eRules.eCompanyRules.isMaterialCompanyType(comp.type) == false)
                {
                    eObj.material_stock ms = new eObj.material_stock();
                    ms.material_type = eRules.eCompanyRules.getCompanyRawType(comp.type);
                    nd = doc.SelectSingleNode("company/raw-materials-in-stock");
                    eObj.material m = new eObj.material();
                    m.date = DateTime.Now;
                    m.id = Guid.NewGuid().ToString();
                    m.volume_in = Double.Parse(nd.InnerText, culture);
                    m.volume_out = 0;
                    m.unit_price = 0;
                    ms.materials.Add(m);
                    comp.material_list.Add(ms);
                }

                //Production Ratio
                comp.production_ratio = eRules.eCompanyRules.getProductModifier(comp.type);

                //Company Stock
                nd = doc.SelectSingleNode("company/stock");
                eObj.stock st = new eObj.stock();
                st.volume_in = double.Parse(nd.InnerText, culture);
                st.volume_out = 0;
                st.production_cost = 0;
                st.date = DateTime.Now;
                comp.company_stock.Add(st);

                //employees
                ndl = doc.SelectNodes("company/employees/employee");
                foreach (XmlNode n in ndl)
                {
                    eObj.employee emp = new eObj.employee();
                    emp.id = Guid.NewGuid().ToString();
                    emp.api_id = n.SelectSingleNode("id").InnerText;
                    emp.name = n.SelectSingleNode("name").InnerText;
                    emp.date_in = DateTime.Now;
                    comp.employee_list.Add(emp);
                }

                if (caller != null) caller("");
                return comp;
            }
            catch (Exception ex)
            {
                throw new Exception("eAPI does not respond\n["+ex.Source+"] "+ex.Message+"\n["+ex.Source+"] "+ex.InnerException);
            }
        }

        //This method should be rewrite when eAPI will be corrected ! (actually, we have a 404 not found
        public bool getMarketForCompany(string industry_id, string country_id, Dictionary<string,string> customPointsTab, out double volume, out double unit_price)
        {
            System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo("en-US");
            volume = 0;
            unit_price = 0;
            eObj.company_type_enum comp_type = getCompanyTypeFromApiId(industry_id);

            //Slash for attribute will be added when replacing string <attr_x>
            string url = "http://api.erepublik.com/v2/feeds/market/<industry_id>/<country_id><attr_1><attr_2><attr_3><attr_4>";
            url = url.Replace("<industry_id>", industry_id);
            url = url.Replace("<country_id>", country_id);
            switch (comp_type)
            {
                case eCompany.eObj.company_type_enum.grain:
                    url = url.Replace("<attr_1>", "");
                    url = url.Replace("<attr_2>", "");
                    url = url.Replace("<attr_3>", "");
                    url = url.Replace("<attr_4>", "");
                    break;
                case eCompany.eObj.company_type_enum.oil:
                    url = url.Replace("<attr_1>", "");
                    url = url.Replace("<attr_2>", "");
                    url = url.Replace("<attr_3>", "");
                    url = url.Replace("<attr_4>", "");
                    break;
                case eCompany.eObj.company_type_enum.iron:
                    url = url.Replace("<attr_1>", "");
                    url = url.Replace("<attr_2>", "");
                    url = url.Replace("<attr_3>", "");
                    url = url.Replace("<attr_4>", "");
                    break;
                case eCompany.eObj.company_type_enum.stone:
                    url = url.Replace("<attr_1>", "");
                    url = url.Replace("<attr_2>", "");
                    url = url.Replace("<attr_3>", "");
                    url = url.Replace("<attr_4>", "");
                    break;
                case eCompany.eObj.company_type_enum.food:
                    url = url.Replace("<attr_1>", "/"+customPointsTab["health"]);
                    url = url.Replace("<attr_2>", "");
                    url = url.Replace("<attr_3>", "");
                    url = url.Replace("<attr_4>", "");
                    break;
                case eCompany.eObj.company_type_enum.moving_tickets:
                    break;
                case eCompany.eObj.company_type_enum.weapons:
                    break;
                case eCompany.eObj.company_type_enum.house:
                    break;
                case eCompany.eObj.company_type_enum.defense_system:
                    break;
                case eCompany.eObj.company_type_enum.hospital:
                    break;
                default:
                    return false;
            }

            Console.WriteLine("Getting Market : " + url);
            HttpWebRequest hwebRequest = (HttpWebRequest)WebRequest.Create(url);
            hwebRequest.Timeout = 60000;
            hwebRequest.ReadWriteTimeout = 60000;
            HttpWebResponse hWebResponse = (HttpWebResponse)hwebRequest.GetResponse();
            XmlTextReader oXmlReader = new XmlTextReader(hWebResponse.GetResponseStream());

            System.Xml.XmlDocument market_doc = new XmlDocument();
            market_doc.Load(oXmlReader);

            XmlNode n = market_doc.SelectSingleNode("offers/offer");
            XmlNode n1 = n.SelectSingleNode("price");
            unit_price = double.Parse(n1.InnerText, culture);
            n1 = n.SelectSingleNode("amount");
            volume = double.Parse(n1.InnerText, culture);
            
            return false;
        }

        private eObj.company_type_enum getCompanyTypeFromApiId(string id)
        {
            if (id == "1")
                return eObj.company_type_enum.food;
            if (id == "2")
                return eObj.company_type_enum.moving_tickets;
            if (id == "5")
                return eObj.company_type_enum.defense_system;
            if (id == "11")
                return eObj.company_type_enum.oil;
            if (id == "10")
                return eObj.company_type_enum.grain;
            if (id == "4")
                return eObj.company_type_enum.hospital;
            if (id == "14")
                return eObj.company_type_enum.iron;
            if (id == "3")
                return eObj.company_type_enum.house;
            if (id == "13")
                return eObj.company_type_enum.stone;
            if (id == "15")
                return eObj.company_type_enum.weapons;
            
            return eObj.company_type_enum.weapons; //hack cause eapi bulshit
        }

        public apiEmployee loadCitizenFromWeb(string employee_id, string employee_name)
        {
            string url = "";
            
            if (employee_id != "")
                url = "http://api.erepublik.com/v2/feeds/citizens/" + employee_id;
            else
                url = "http://api.erepublik.com/v2/feeds/citizen_by_name/xml/" +  Uri.EscapeDataString(employee_name);
            
            System.Console.WriteLine("Loading citizen "+employee_id+" : " + url);
            HttpWebRequest hwebRequest = (HttpWebRequest)WebRequest.Create(url);
            hwebRequest.Timeout = 60000;
            hwebRequest.ReadWriteTimeout = 60000;
            HttpWebResponse hWebResponse = (HttpWebResponse)hwebRequest.GetResponse();
            XmlTextReader oXmlReader = new XmlTextReader(hWebResponse.GetResponseStream());

            System.Xml.XmlDocument citizen_doc = new XmlDocument();
            citizen_doc.Load(oXmlReader);

            apiEmployee apiE = new apiEmployee();

            XmlNode nd = citizen_doc.SelectSingleNode("citizen/avatar-link");
            if (nd == null)
                return null;
            apiE.avatar_link = nd.InnerText;

            nd = citizen_doc.SelectSingleNode("citizen/name");
            if (nd == null)
                return null;
            apiE.name = nd.InnerText;

            nd = citizen_doc.SelectSingleNode("citizen/level");
            if (nd == null)
                return null;
            apiE.level = nd.InnerText;

            nd = citizen_doc.SelectSingleNode("citizen/wellness");
            if (nd == null)
                return null;
            apiE.wellness = nd.InnerText;

            nd = citizen_doc.SelectSingleNode("citizen/id");
            if (nd == null)
                return null;
            apiE.id = nd.InnerText;

            System.Console.WriteLine("Citizen " + employee_id + " Loaded");

            return apiE;
        }

        public List<string> loadCompanyEmployeeListFromWeb(string company_id)
        {
            List<string> id_list = new List<string>();
            try
            {
                System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo("en-US");

                HttpWebRequest hwebRequest = (HttpWebRequest)WebRequest.Create("http://api.erepublik.com/v2/feeds/companies/" + company_id);
                hwebRequest.Timeout = 60000;
                hwebRequest.ReadWriteTimeout = 60000;
                HttpWebResponse hWebResponse = (HttpWebResponse)hwebRequest.GetResponse();
                XmlTextReader oXmlReader = new XmlTextReader(hWebResponse.GetResponseStream());

                System.Xml.XmlDocument doc = new XmlDocument();
                doc.Load(oXmlReader);

                //employees
                XmlNodeList ndl = doc.SelectNodes("company/employees/employee");
                foreach (XmlNode n in ndl)
                {
                    id_list.Add(n.SelectSingleNode("id").InnerText);
                }

                return id_list;
            }
            catch (Exception ex)
            {
                throw new Exception("eAPI does not respond\n[" + ex.Source + "] " + ex.Message + "\n[" + ex.Source + "] " + ex.InnerException);
            }
        }
    }

    public class apiEmployee
    {
        public string id;
        public string name;
        public string avatar_link;
        public string level;
        public string wellness;
    }
}
